require 'benchmark'
require 'pathname'

require 'ru-slow/kernel'

module RuSlow
  extend self

  attr_accessor :root

  #
  # Add a new call to the profiler.
  #
  # @param [String] name
  #   the name of the thing to benchmark (like a label)
  # @param [Benchmark] result
  #   the result of the benchmark
  #
  # @return [Boolean]
  #   true if the benchmark was added, false if the benchmark already
  #   exists
  #
  def add(name, result)
    if profiler.has_key?(name)
      false
    else
      line = caller[1].split(' ', 2).first[0..-4]

      if line.include?(root)
        profiler[name] = result
        true
      else
        false
      end
    end
  end

  #
  # Generate the report.
  #
  def report!
    by_time = profiler.sort_by { |_, t| -t.total }
    padding = by_time.map(&:first).group_by(&:size).max.last.first.length

    puts "\n"*3
    puts "Label".ljust(padding) + ' Real'
    puts '-'*padding + '---------'

    by_time.each do |label, benchmark|
      puts label.ljust(padding) + ' ' + benchmark.real.to_s
    end
  rescue => e
    Kernel.warn "There was an error running the report: #{e.message}"
  end

  private

    # @return [Hash]
    def profiler
      @profiler ||= {}
    end
end

#
# Calculate the calling lib path when ru-slow is required.
#
kaller = Pathname.new(caller.last.split(':', 2).first).expand_path
root   = nil
kaller.ascend do |dir|
  path = dir.join('Gemfile')

  if path.exist?
    root = dir.to_s
    break
  end
end

RuSlow.root = root
